/* course-window.c
 *
 * Copyright 2023 korack
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */

#include "CourseWindow.h"

#include "CourseCell.h"
#include "CourseObject.h"
#include "config.h"

#include <object_v2/object_v2.h>

struct _CourseWindow
{
        AdwApplicationWindow parent_instance;

        /* Template widgets */
        AdwHeaderBar*      header_bar;
        GtkWidget*         prev_button;
        GtkWidget*         next_button;
        GtkGrid*           main_grid;
        GtkScrolledWindow* scroll;

        /* CourseObject */
        CourseObject* course;
        ObjectString* error;
};

G_DEFINE_FINAL_TYPE (CourseWindow, course_window, ADW_TYPE_APPLICATION_WINDOW)

static void
course_window_class_finalize (GObject* object)
{
        CourseWindow* window = COURSE_WINDOW (object);
        object_unref (window->course);
        object_unref (window->error);
        G_OBJECT_CLASS (course_window_parent_class)->finalize (object);
}

static void
course_window_class_init (CourseWindowClass* klass)
{
        GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (klass);
        GObjectClass*   object_class = G_OBJECT_CLASS (klass);

        gtk_widget_class_set_template_from_resource (
                widget_class,
                "/org/korack/kcourse/CourseWindow.ui");
        gtk_widget_class_bind_template_child (widget_class,
                                              CourseWindow,
                                              header_bar);
        gtk_widget_class_bind_template_child (widget_class,
                                              CourseWindow,
                                              prev_button);
        gtk_widget_class_bind_template_child (widget_class,
                                              CourseWindow,
                                              next_button);
        gtk_widget_class_bind_template_child (widget_class,
                                              CourseWindow,
                                              main_grid);
        gtk_widget_class_bind_template_child (widget_class,
                                              CourseWindow,
                                              scroll);

        object_class->finalize = course_window_class_finalize;
}

static void
course_window_alert_not_file_dialog (CourseWindow* self)
{
        GtkWidget* alert;
        alert = adw_message_dialog_new (GTK_WINDOW (self),
                                        "课程表加载失败",
                                        self->error->charset);
        adw_message_dialog_add_response (ADW_MESSAGE_DIALOG (alert),
                                         "cancle",
                                         "行嘛");
        gtk_widget_set_visible (self->next_button, false);
        gtk_widget_set_visible (self->prev_button, false);
        gtk_window_present (GTK_WINDOW (alert));
}

static void
course_window_render_table (CourseWindow* self)
{
        bool          is_today = false;
        GtkWidget*    cell;
        ObjectString* str;
        DateObject    _now_date, *today;
        static char   buf[30];
        g_return_if_fail ((self != NULL));
        if (!self->course->is_init) {
                OBJECT_WARNING_TOOL (CourseWindow,
                                     render_table,
                                     "课程表尚未初始化！若课程表存在，请打开终"
                                     "端查看课程表加载的详情。\n");
                object_string_append_string (self->error,
                                             "\n当前课程表打开失败，更多信息请"
                                             "在终端执行 kcourse 以查看！");
                course_window_alert_not_file_dialog (self);
                g_return_if_fail ((self->course->is_init));
        }

        str = object_string_new_with (self->course->student_info->charset);
        sprintf (buf, "(第 %d 周)", self->course->current_week);
        object_string_append_string (str, buf);
        gtk_window_set_title (GTK_WINDOW (self), str->charset);
        object_unref (str);

        date_object_get_monday_of_current_week (self->course->start_date,
                                                self->course->current_week,
                                                &_now_date);
        today = date_object_new_with_today ();
        for (int j = 0; j < 8; ++j) {
                if (j > 0) {
                        if (j > 1)
                                date_object_add_days (&_now_date, 1);
                        is_today = !date_object_compare (&_now_date, today);
                }
                for (int i = 0; i < 15; ++i) {
                        cell = gtk_grid_get_child_at (
                                GTK_GRID (self->main_grid),
                                j,
                                i);
                        course_cell_set_course (COURSE_CELL (cell),
                                                self->course->table[i][j],
                                                i,
                                                is_today);
                }
                if (is_today)
                        is_today = false;
        }
        object_unref (today);
}

static void
course_window_get_prev_week (GSimpleAction* action,
                             GVariant*      parameter,
                             gpointer       user_data)
{
        CourseWindow* window;
        g_return_if_fail (COURSE_IS_WINDOW (user_data));

        window = COURSE_WINDOW (user_data);

        course_object_show_course_of_prev_week (window->course);
        course_window_render_table (window);
}

static void
course_window_get_next_week (GSimpleAction* action,
                             GVariant*      parameter,
                             gpointer       user_data)
{
        CourseWindow* window;
        g_return_if_fail (COURSE_IS_WINDOW (user_data));

        window = COURSE_WINDOW (user_data);

        course_object_show_course_of_next_week (window->course);
        course_window_render_table (window);
}

static const GActionEntry win_actions[] = {
        {"prev_week", course_window_get_prev_week},
        {"next_week", course_window_get_next_week},
};

void
course_window_set_course (CourseWindow* window, CourseObject* course)
{
        g_assert (COURSE_IS_WINDOW (window));
        window->course = object_reference_to (course, COURSE_OBJECT);
        window->error  = object_reference_to ((course ? course->_error : NULL),
                                             OBJECT_STRING);
}

inline void
course_window_render_once (CourseWindow* window)
{
        g_assert (COURSE_IS_WINDOW (window));
        course_window_render_table (window);
}

static void
course_window_init (CourseWindow* self)
{
        CourseCell* cell;
        gtk_widget_init_template (GTK_WIDGET (self));
        g_action_map_add_action_entries (G_ACTION_MAP (self),
                                         win_actions,
                                         G_N_ELEMENTS (win_actions),
                                         self);
        for (int i = 0; i < 15; ++i) {
                for (int j = 0; j < 8; ++j) {
                        cell = course_cell_new ();
                        if (i == 0)
                                course_cell_set_size (cell, 120, 50);
                        gtk_grid_attach (self->main_grid,
                                         GTK_WIDGET (cell),
                                         j,
                                         i,
                                         1,
                                         1);
                }
        }
        self->course = NULL;
        self->error  = NULL;
}
